/*
Copyright (C) 2022-2024 Inspur Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package controller

import (
	"did-service/auth"
	"did-service/bean/model"
	"did-service/bean/param"
	"did-service/bean/view"
	"did-service/common/constant"
	"did-service/common/http"
	"did-service/common/jwt"
	"did-service/config"
	"did-service/plugins/cryptoprovider"
	"did-service/plugins/sessionmgr"
	"strconv"

	"github.com/emicklei/go-restful"
)

func (dc *DidController) Login(req *restful.Request, resp *restful.Response) {
	var loginParam param.LoginParam
	if err := req.ReadEntity(&loginParam); err != nil {
		log.Errorf("login read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if loginParam.UserName == "" || loginParam.Password == "" {
		http.Failed(resp, "请求参数不合法！")
		return
	}

	locked, msg := dc.lockTool.IsAccountLocked(loginParam.UserName)
	if locked {
		http.Failed(resp, msg)
		return
	}

	userDetail, err := dc.srv.GetUserByName(loginParam.UserName)
	if err != nil {
		log.Errorf("login error: %v", err)
		http.Failed(resp, "登录失败！")
		return
	}
	if userDetail == nil {
		log.Warning("user not exist")
		http.Failed(resp, "用户或密码错误！")
		dc.lockTool.HandleLoginFailed(loginParam.UserName)
		return
	}

	// 获取密码
	//password := sha256.Sha256(loginParam.Password + config.Get("did.salt", constant.DefaultSalt))
	password := loginParam.Password
	if !cryptoprovider.Get().Check(userDetail.Pwd, password) {
		log.Warning("password wrong")
		http.Failed(resp, "用户或密码错误！")
		dc.lockTool.HandleLoginFailed(loginParam.UserName)
		return
	}

	token := jwt.GenerateToken(userDetail.Id, userDetail.UserName, userDetail.NickName, userDetail.UserType)
	if token == "" {
		log.Error("failed to generate token")
		http.Failed(resp, "令牌生成失败！")
		return
	}
	useSession := config.GetBool("did.auth.use-session")
	if useSession {
		sessionmgr.Get().Add(userDetail.Id, token, req.Request)
	}
	loginView := view.LoginView{Token: token}
	resp.Header().Add("Authorization", token)
	http.OkWithData(resp, "登录成功", loginView)
	dc.lockTool.HandleLoginSuccess(loginParam.UserName)
}

func (dc *DidController) Logout(req *restful.Request, resp *restful.Response) {
	userId := auth.GetCurrentWalletId(req)
	sessionmgr.Get().Remove(userId)
	http.Ok(resp, "登出成功")
}

func (dc *DidController) ApplyDidDocument(req *restful.Request, resp *restful.Response) {
	document, err := dc.srv.ApplyDidDocument()
	if err != nil {
		log.Errorf("apply did document error: %v", err)
		http.Failed(resp, "申请失败")
		return
	}
	http.OkWithData(resp, "申请成功", document)
}

func (dc *DidController) QueryUserList(req *restful.Request, resp *restful.Response) {

	currentUserType := auth.GetCurrentUserType(req)
	if currentUserType != constant.UserTypeAdmin {
		http.Failed(resp, "用户无权限！")
		return
	}

	strPageSize := req.QueryParameter("pageSize")
	strPageNo := req.QueryParameter("pageNum")
	userType := req.QueryParameter("userType")
	nickName := req.QueryParameter("nickName")
	userName := req.QueryParameter("userName")
	pageSize := 5
	if strPageSize != "" {
		pageSize, _ = strconv.Atoi(strPageSize)
	}
	pageNo := 1
	if strPageNo != "" {
		pageNo, _ = strconv.Atoi(strPageNo)
	}

	page := dc.srv.QueryUserList(userType, nickName, userName, pageSize, pageNo)
	http.OkWithData(resp, "查询成功", page)
}

func (dc *DidController) RegisterUser(req *restful.Request, resp *restful.Response) {
	var userParam param.RegisterUserParam
	if err := req.ReadEntity(&userParam); err != nil {
		log.Errorf("register user read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.UserType != constant.UserTypePerson && userParam.UserType != constant.UserTypeIssuer &&
		userParam.UserType != constant.UserTypeEnterprise {
		log.Errorf("only person user, org user, enterprise user can be created!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.Password == "" {
		log.Errorf("usertype or password empty!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.UserName == "" {
		log.Errorf("username is empty!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	walletId, err := dc.srv.RegisterUser(userParam)
	if err != nil {
		log.Errorf("register user error: %s", err)
		http.Failed(resp, err.Error())
		return
	}

	_, err = dc.srv.CreateDid(walletId)
	if err != nil {
		log.Errorf("create did error: %v", err)
		http.Failed(resp, "用户创建成功，DID申请失败！")
		return
	}

	http.OkWithData(resp, "创建成功", struct {
		WalletId string `json:"walletId"`
	}{walletId})

}

func (dc *DidController) CreateUser(req *restful.Request, resp *restful.Response) {

	currentUserType := auth.GetCurrentUserType(req)
	if currentUserType != constant.UserTypeAdmin {
		http.Failed(resp, "用户无权限！")
		return
	}
	var userParam param.UserWallet

	if err := req.ReadEntity(&userParam); err != nil {
		log.Errorf("create user read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.UserType != constant.UserTypePerson && userParam.UserType != constant.UserTypeIssuer &&
		userParam.UserType != constant.UserTypeEnterprise {
		log.Errorf("only person user, org user, enterprise user can be created!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.Pwd == "" {
		log.Errorf("usertype or password empty!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if userParam.UserName == "" {
		log.Errorf("username is empty!")
		http.Failed(resp, "请求参数不合法！")
		return
	}

	walletId, err := dc.srv.CreateUser(userParam)
	if err != nil {
		log.Errorf("create user error: %s", err)
		http.Failed(resp, err.Error())
		return
	}

	_, err = dc.srv.CreateDid(walletId)
	if err != nil {
		log.Errorf("create did error: %v", err)
		http.Failed(resp, "用户创建成功，DID申请失败！")
		return
	}

	_, err = dc.srv.CreateApiKey(walletId)
	if err != nil {
		log.Errorf("create did, create api key error: %v", err)
		http.Failed(resp, "创建ApiKey失败")
		return
	}

	http.OkWithData(resp, "创建成功", struct {
		WalletId string `json:"walletId"`
	}{walletId})
}

func (dc *DidController) PutUser(req *restful.Request, resp *restful.Response) {

	currentUserType := auth.GetCurrentUserType(req)
	if currentUserType != constant.UserTypeAdmin {
		http.Failed(resp, "用户无权限！")
		return
	}
	id := req.PathParameter("id")
	var userParam param.PutUserParam
	if err := req.ReadEntity(&userParam); err != nil {
		log.Errorf("update user read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}
	pwd := userParam.Pwd
	if id == "" || pwd == "" {
		log.Error("id or pwd all empty!")
		http.Failed(resp, "请求参数不合法")
		return
	}
	err := dc.srv.PutUser(id, pwd)
	if err != nil {
		log.Errorf("update user error: %s", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	http.Ok(resp, "修改成功")
}

func (dc *DidController) GetUserInfo(req *restful.Request, resp *restful.Response) {
	currentUserType := auth.GetCurrentUserType(req)
	currentUserName := auth.GetCurrentUserName(req)
	currentWalletId := auth.GetCurrentWalletId(req)
	currentNickName := auth.GetCurrentNickName(req)
	info := model.UserInfo{
		Id:       currentWalletId,
		UserName: currentUserName,
		NickName: currentNickName,
		UserType: currentUserType,
	}
	http.OkWithData(resp, "查询成功", info)
}
